<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
import {
	addClassname,
	addClassnameList,
	deleteClassname,
	getClassnameListService
} from '../../../../api/education/classname'
import { TClass } from '@/Types/education'
import { exportToExcel, importFromExcel } from './component/excel'
import ExcelPreview from './component/ExcelPreview.vue'
import { getUserListByClassIdListService } from '@/api/user_classname'
import router from '@/router'

// 初始化
const loading = ref(false)

// 班级表格数据
const tableData = ref<(TClass & { counsellorInfo?: { uname: string; phoneNumber: string } })[]>([])

// 对话框相关
const formRef = ref<FormInstance>()
const dialogVisible = ref(false)
const dialogType = ref<'add' | 'edit'>('add')

// 表单数据
const form = ref({
	classId: 0,
	level: '',
	academy: '',
	major: '',
	grade: 0,
	classname: '',
	counsellor: '',
	phoneNumber: ''
})

// 获取班级列表数据
const getClassList = async () => {
	try {
		const res = await getClassnameListService()
		if (res.data.code === 1) {
			tableData.value = res.data.data
			generateTreeData()
		} else {
			ElMessage.error(`获取班级数据失败：${res.data.message || '未知错误'}`)
		}
	} catch (error) {
		// console.error('获取班级数据时发生错误:', error)
		ElMessage.error('获取班级数据失败，请稍后重试')
	}
}
// 获取对应的辅导员数据
const getCounsellor = async () => {
	// 只在选中年级节点时处理
	if (selectedNode.value?.type !== 'grade') return

	// 获取选中节点的完整路径信息，并处理年级数据
	const selectedGrade = Number(selectedNode.value.label.replace('级', ''))
	const selectedMajor = selectedNode.value.parent.label
	const selectedAcademy = selectedNode.value.parent.parent.label

	// 过滤出符合条件的班级数据
	const classData = tableData.value.filter(
		(item) =>
			item.grade === selectedGrade &&
			item.major === selectedMajor &&
			item.academy === selectedAcademy
	)

	// 获取班级ID列表
	const classIdLIst = classData.map((item) => item.classId!) // !确信classId不会为null、undefined

	// 获取辅导员信息
	const res = await getUserListByClassIdListService(3, classIdLIst)
	if (res.data.code === 1 && res.data.data.length > 0) {
		// 更新表格数据中的辅导员信息
		tableData.value = tableData.value.map((item) => {
			// 找到当前班级在过滤后的班级数据中的索引
			const index = classData.findIndex(
				(c) =>
					c.grade === item.grade &&
					c.major === item.major &&
					c.academy === item.academy &&
					c.classname === item.classname
			)

			// 如果找到对应索引且有对应的辅导员信息
			const counsellorInfo = index !== -1 ? res.data.data[index] : undefined

			return {
				...item,
				counsellorInfo: counsellorInfo
					? {
							uname: counsellorInfo.uname,
							phoneNumber: counsellorInfo.phoneNumber
						}
					: undefined
			}
		})
	}
}

/**
 * 模块名:树状结构
 * 代码描述:
 * 作者:mck
 * 创建时间:2025/02/05 17:51:27
 */

// 树形数据结构
const treeData = ref<any[]>([])
// 树形配置
const defaultProps = {
	children: 'children',
	label: 'label'
}
// 当前选中的节点
const selectedNode = ref()
// 添加类型定义(ts无法确定展开操作符作用的对象类型)
interface TreeNode {
	id: string
	label: string
	type: string
	children?: TreeNode[]
}

// 生成树形数据
const generateTreeData = () => {
	// 创建一个 Map 对象，用于存储学院层级的树形结构
	// Map 的键是学院名称，值是该学院对应的节点信息
	const academyMap = new Map()

	// 遍历班级数据，构建树形结构
	tableData.value.forEach((classItem) => {
		// 处理学院层级
		// 检查当前学院是否已经存在于 academyMap 中
		if (!academyMap.has(classItem.academy)) {
			// 如果不存在，则创建一个新的学院节点，并添加到 academyMap 中
			academyMap.set(classItem.academy, {
				id: `academy-${classItem.academy}`, // 学院节点的唯一标识
				label: classItem.academy, // 学院名称
				type: 'college', // 节点类型（学院）
				children: new Map() // 子节点（专业层级），使用 Map 存储
			})
		}

		// 获取当前学院节点
		const academyNode = academyMap.get(classItem.academy)
		// 获取学院节点的子节点（专业层级的 Map）
		const majorMap = academyNode.children

		// 处理专业层级
		// 检查当前专业是否已经存在于 majorMap 中
		if (!majorMap.has(classItem.major)) {
			// 如果不存在，则创建一个新的专业节点，并添加到 majorMap 中
			majorMap.set(classItem.major, {
				id: `major-${classItem.major}`, // 专业节点的唯一标识
				label: classItem.major, // 专业名称
				type: 'major', // 节点类型（专业）
				children: new Map() // 子节点（年级层级），使用 Map 存储
			})
		}

		// 获取当前专业节点
		const majorNode = majorMap.get(classItem.major)
		// 获取专业节点的子节点（年级层级的 Map）
		const gradeMap = majorNode.children

		// 处理年级层级
		// 构造年级的唯一标识（例如 "2023级"）
		const gradeKey = `${classItem.grade}级`
		// 检查当前年级是否已经存在于 gradeMap 中
		if (!gradeMap.has(gradeKey)) {
			// 如果不存在，则创建一个新的年级节点，并添加到 gradeMap 中
			gradeMap.set(gradeKey, {
				id: `grade-${classItem.grade}`, // 年级节点的唯一标识
				label: gradeKey, // 年级名称（例如 "2023级"）
				type: 'grade' // 节点类型（年级）
			})
		}
	})

	// 将 Map 结构转换为数组结构，生成最终的树形数据
	treeData.value = Array.from(academyMap.values()).map((academy: any) => ({
		...(academy as TreeNode), // 展开学院节点的属性
		children: Array.from(academy.children.values()).map((major: any) => ({
			...(major as TreeNode), // 展开专业节点的属性
			children: Array.from(major.children.values()) // 展开年级节点的属性
		}))
	}))
}
// [
//   { academy: '计算机学院', major: '软件工程', grade: 2023 },
//   { academy: '计算机学院', major: '软件工程', grade: 2022 },
//   { academy: '数学学院', major: '应用数学', grade: 2023 }
// ]
// 效果如下：
// [
// 	{
// 		id: 'academy-计算机学院',
// 		label: '计算机学院',
// 		type: 'college',
// 		children: [
// 			{
// 				id: 'major-软件工程',
// 				label: '软件工程',
// 				type: 'major',
// 				children: [
// 					{ id: 'grade-2023', label: '2023级', type: 'grade' },
// 					{ id: 'grade-2022', label: '2022级', type: 'grade' }
// 				]
// 			}
// 		]
// 	},
// 	{
// 		id: 'academy-数学学院',
// 		label: '数学学院',
// 		type: 'college',
// 		children: [
// 			{
// 				id: 'major-应用数学',
// 				label: '应用数学',
// 				type: 'major',
// 				children: [{ id: 'grade-2023', label: '2023级', type: 'grade' }]
// 			}
// 		]
// 	}
// ]

// 节点点击事件
const handleNodeClick = (data: any, node: any) => {
	// 为当前节点添加父节点引用
	const newData = { ...data }
	if (node.parent) {
		newData.parent = {
			...node.parent.data,
			parent: node.parent.parent?.data
		}
	}
	selectedNode.value = newData
	getCounsellor()
}

/**
 * 模块名: 数据提交
 * 代码描述:
 * 作者:mck
 * 创建时间:2025/02/05 17:54:42
 */
// 添加班级
const handleAdd = () => {
	formRef.value?.resetFields()
	dialogType.value = 'add'
	dialogVisible.value = true
}

const handleSubmitClassname = async () => {
	if (!formRef.value) return

	await formRef.value.validate(async (valid: boolean) => {
		if (!valid) return
		loading.value = true

		const classData = {
			...form.value,
			grade: Number(form.value.grade),
			classname: Number(form.value.classname)
		}

		if (dialogType.value === 'add') {
			const res = await addClassname(classData)
			if (res.data.code === 1) {
				tableData.value.push({
					...classData
				})

				generateTreeData()
				loading.value = true
				ElMessage.success('添加班级成功')
				dialogVisible.value = false
			} else {
				ElMessage.error(`添加失败：${res.data.msg || '未知错误'}`)
			}
		}

		return
	})
}

// // 编辑班级
// const handleEdit = (row: typeof form) => {
// 	dialogType.value = 'edit'
// 	;(Object.keys(form) as Array<keyof typeof form>).forEach((key) => {
// 		form[key] = row[key]
// 	})
// 	dialogVisible.value = true
// }

// 删除班级
const handleDelete = (row: any) => {
	// console.log(row)

	ElMessageBox.confirm('确认删除该班级吗？', '提示', {
		type: 'warning'
	}).then(async () => {
		const res = await deleteClassname(row.classId)
		if (res.data.code === 1) {
			ElMessage.success('删除成功')
		} else {
			ElMessage.error(`删除失败：${res.data.message || '未知错误'}`)
		}
		getClassList()
	})
}

// 树形导航

// 获取列表标题
const getListTitle = computed(() => {
	if (!selectedNode.value) return '班级列表'

	// 获取当前节点的所有父节点路径
	const getNodePath = (node: any) => {
		const path = []
		let current = node
		while (current) {
			path.unshift(current.label)
			current = current.parent
		}
		return path[0] + (path.length > 1 ? ' - ' + path.slice(1).join(' - ') : '')
	}

	return getNodePath(selectedNode.value)
})

/**
 * 模块名: 获取成绩数据
 * 代码描述:
 * 作者:mck
 * 创建时间:2025/02/14 20:25:20
 */
// 自定义事件
const emit = defineEmits(['set-class-info'])

// 查看班级成绩时
const handleViewScore = (row: any) => {
	// console.log(row)
	// emit('set-class-info', row) // 传递班级信息

	router.push(`/classScoreInfo/${row.classId}`)
}

/**
 * 模块名:excel数据处理
 * 代码描述:
 * 作者:mck
 * 创建时间:2025/02/13 15:44:56
 */
// 初始化
const uploadExcelRef = ref()
// Excel预览相关
const excelPreviewSetting = ref({
	visible: false,
	type: 'import',
	data: [] as TClass[]
})

// 处理导入
const handleImport = async (file: any) => {
	try {
		const result = await importFromExcel(file.raw)
		ElMessage.success('导入成功')
		excelPreviewSetting.value.visible = true
		excelPreviewSetting.value.type = 'import'
		excelPreviewSetting.value.data = result.data
	} catch (error) {
		// console.error('导入失败:', error)
		ElMessage.error('导入失败，请稍后重试')
	} finally {
		uploadExcelRef.value.clearFiles()
	}
}

// 处理导出
const handleExport = () => {
	if (!selectedNode.value || selectedNode.value.type !== 'grade') {
		ElMessage.warning('请先选择一个年级再导出数据')
		return
	}

	if (!filteredTableData.value.length) {
		ElMessage.warning('当前没有可导出的数据')
		return
	}

	excelPreviewSetting.value.data = filteredTableData.value.map((item) => ({
		academy: item.academy,
		major: item.major,
		grade: item.grade,
		classname: item.classname,
		counsellor: item.counsellorInfo?.uname || '',
		phoneNumber: item.counsellorInfo?.phoneNumber || ''
	}))
	excelPreviewSetting.value.type = 'export'
	excelPreviewSetting.value.visible = true
}

// 确认excel弹窗数据
const handlePreviewConfirm = async (data: TClass[]) => {
	if (excelPreviewSetting.value.type === 'import') {
		// 处理导入确认
		if (!data.length) {
			ElMessage.warning('导入数据不能为空')
			return
		} else {
			// console.log(data)
			const res = await addClassnameList(data)
			// console.log(res)

			if (res.data.code === 1) {
				ElMessage.success('导入成功')
			} else {
				ElMessage.error(`导入失败：${res.data.message || '未知错误'}`)
			}

			getClassList()
		}
	} else {
		// 处理导出确认
		exportToExcel(data, '班级信息')
	}
}

/**
 * 模块名: 数据处理
 * 代码描述:
 * 作者:mck
 * 创建时间:2025/02/14 20:25:20
 */
// 计算属性：判断是否显示表格
const showTable = computed(() => {
	return selectedNode.value?.type === 'grade'
})

// 根据选中节点过滤表格数据
const filteredTableData = computed(() => {
	// console.log(tableData.value)
	if (!selectedNode.value || selectedNode.value.type !== 'grade') return []

	return tableData.value.filter((item) => {
		const selectedGrade = selectedNode.value.label.replace('级', '')
		const selectedMajor = selectedNode.value.parent.label
		const selectedAcademy = selectedNode.value.parent.parent.label

		return (
			item.grade?.toString() === selectedGrade &&
			item.major === selectedMajor &&
			item.academy === selectedAcademy
		)
	})
})

// 表单验证规则
const rules = {
	level: [{ required: true, message: '请选择学历', trigger: 'change' }],
	academy: [{ required: true, message: '请输入学院名称', trigger: 'blur' }],
	major: [{ required: true, message: '请输入专业名称', trigger: 'blur' }],
	grade: [{ required: true, message: '请选择年级', trigger: 'change' }],
	classname: [{ required: true, message: '请输入班级', trigger: 'blur' }]
}

// 页面加载时获取数据
onMounted(() => {
	getClassList()
})
</script>

<template>
	<div class="class-manage">
		<!-- 左侧树形导航 -->
		<el-card class="tree-card">
			<template #header>
				<div class="card-header">
					<span>班级管理</span>
					<el-button type="primary" @click="handleAdd">添加班级</el-button>
				</div>
			</template>
			<el-tree
				:data="treeData"
				:props="defaultProps"
				:highlight-current="true"
				@node-click="handleNodeClick"
			>
				<template #default="{ data }">
					<span class="custom-tree-node">
						<span>{{ data.label }}</span>
					</span>
				</template>
			</el-tree>
			<div class="class-Import-button">
				<el-upload
					ref="uploadExcelRef"
					class="upload-demo"
					:auto-upload="false"
					:show-file-list="false"
					accept=".xlsx,.xls"
					:limit="1"
					@change="handleImport"
				>
					<!-- <el-button>导入</el-button> -->
				</el-upload>
				<!-- <el-button @click="handleExport">导出</el-button> -->
			</div>
		</el-card>

		<!-- 右侧班级列表 -->
		<el-card class="list-card" v-if="showTable">
			<template #header>
				<div class="card-header">
					<span>{{ getListTitle }}</span>
				</div>
			</template>

			<el-table
				:data="filteredTableData"
				border
				:default-sort="{ prop: 'classname', order: 'ascending' }"
				height="100%"
			>
				<el-table-column prop="classname" label="班级" sortable width="80">
					<template #default="{ row }">
						<span>{{ String(row.classname) + '班' }}</span>
					</template>
				</el-table-column>
				<el-table-column prop="counsellorInfo.uname" label="辅导员" width="80">
					<template #default="{ row }">
						<span>{{ row.counsellorInfo?.uname || '-' }}</span>
					</template>
				</el-table-column>
				<el-table-column prop="counsellorInfo.phoneNumber" label="联系电话" width="120">
					<template #default="{ row }">
						<span>{{ row.counsellorInfo?.phoneNumber || '-' }}</span>
					</template>
				</el-table-column>
				<el-table-column label="操作" fixed="right">
					<template #default="{ row }">
						<el-button type="primary" link @click="handleViewScore(row)">查看成绩</el-button>
						<!-- <el-button type="warning" link @click="handleEdit(row)">编辑</el-button> -->
						<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
					</template>
				</el-table-column>
			</el-table>
		</el-card>

		<!-- 添加班级对话框 -->
		<el-dialog
			v-model="dialogVisible"
			:title="dialogType === 'add' ? '添加班级' : '编辑班级'"
			width="450px"
		>
			<el-form
				ref="formRef"
				:model="form"
				:rules="rules"
				v-loading="loading"
				label-width="80px"
				class="dialog-form"
			>
				<el-form-item label="学历" prop="level">
					<el-select v-model="form.level" placeholder="请选择学历">
						<el-option label="本科" value="undergrad" />
						<el-option label="专科" value="vocEd" />
					</el-select>
				</el-form-item>
				<el-form-item label="学院" prop="academy">
					<el-input v-model="form.academy" placeholder="请输入学院名称" />
				</el-form-item>
				<el-form-item label="专业" prop="major">
					<el-input v-model="form.major" placeholder="请输入专业名称" />
				</el-form-item>
				<el-form-item label="年级" prop="grade">
					<el-input-number v-model="form.grade" :min="2018" :max="2050" placeholder="请输入年级" />
				</el-form-item>
				<el-form-item label="班级" prop="classname">
					<el-input v-model="form.classname" placeholder="请输入班级" />
				</el-form-item>
			</el-form>
			<template #footer>
				<el-button @click="dialogVisible = false">取消</el-button>
				<el-button type="primary" @click="handleSubmitClassname">确定</el-button>
			</template>
		</el-dialog>

		<!-- excel数据预览对话框 -->
		<ExcelPreview
			:excelPreviewSetting="excelPreviewSetting"
			@confirm="handlePreviewConfirm"
			@cancel="excelPreviewSetting.visible = false"
		/>
	</div>
</template>

<style scoped lang="scss">
.class-manage {
	display: flex;
	// flex-direction: column;
	gap: 20px;
	height: 100%;

	.tree-card {
		width: 300px;
		height: 100%;
		position: relative;

		.custom-tree-node {
			flex: 1;
			display: flex;
			align-items: center;
			justify-content: space-between;
			padding-right: 8px;

			.operations {
				display: none;
			}

			&:hover .operations {
				display: inline-flex;
				gap: 8px;
			}
		}

		.class-Import-button {
			display: flex;
			gap: 10px;
			position: absolute;
			bottom: 10px;
			right: 10px;
		}
	}

	.list-card {
		flex: 1;
		height: 100%;
	}

	.card-header {
		display: flex;
		justify-content: space-between;
		align-items: center;
	}

	.pagination-container {
		margin-top: 20px;
		display: flex;
		justify-content: flex-end;
	}

	:deep(.el-dialog) {
		padding: 30px;
	}
}
</style>
